home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr40 / x1j4_src.zip / L2A.C < prev    next >
Text File  |  1995-01-21  |  44KB  |  890 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2A.C   -   Level 2, Teil 1                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:                                                          *
  22. *                                                                          *
  23. * G8KBB version X1J- added register keyword to compress code a bit         *
  24. *                    add audit functions conditionally on MANAGED          *
  25. *                    add KISS drivers conditionally on KISSMODE            *
  26. *                    add MHEARD command audit hooks on MONITORCMD          *
  27. *                    add Auditing support                                  *
  28. *                    add Access Control List support conditionally on ACL  *
  29. *                    add support for welcome msg on alias uplink           *
  30. *                    add support for level 2 stats gathering               *
  31. *                    add MTU command support optionally on MOD_MTU         *
  32. *                    add nodigi control on uplinks to node                 *
  33. *                    add support for 3 aliases for BBS, HOST & DXCluster   *
  34. *                    remove spurious '== 1' and similar structures         *
  35. *                                                                          *
  36. * September 1993 - released as TheNet X-1J                                 *
  37. *                                                                          *
  38. * Add l3 heard list optionally on L3MONITOR                                *
  39. * Correct buffer loss bug in l2rx()                                        *
  40. * Minor speedups to the code                                               *
  41. *                                                                          *
  42. * Released as TheNet X-1J release 4, January 1995                          *
  43. \**************************************************************************/
  44.  
  45.  
  46.  
  47.  
  48.  
  49. /*                                                             Includes   */
  50. /**************************************************************************/
  51.  
  52. #include "all.h"         /* allgemeine Festlegungen                       */
  53. #include "tntyp.h"       /* Festlegungen/Datenstrukturen fuer den Level 2 */
  54. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  55. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  56.  
  57.  
  58. #ifdef MANAGED
  59. #ifdef BANKED
  60. extern char L2audit[];
  61. #else
  62. char L2audit[] = "L2    `";    /* this string identifies level 2 audit msgs */
  63. #endif
  64. #endif
  65.  
  66.  
  67. /**************************************************************************\
  68. *                                                                          *
  69. * "level 2"                                                                *
  70. *                                                                          *
  71. * Der Level 2. Es werden alle Level-2-internen Aktionen ausgefuehrt und    *
  72. * Meldungen an hoehere Level weitergegeben (Informationstransfer von/zum   *
  73. * Level 2 und Kommandos an den Level 2 geschehen von ausserhalb).          *
  74. *                                                                          *
  75. *                                                                          *
  76. * Der Level 2 laeuft wie folgt ab :                                        *
  77. *                                                                          *
  78. *   - Aufruf von l2init()                                                  *
  79. *                                                                          *
  80. *   - zyklisches Aufrufen von l2() und l2timr(ticks)                       *
  81. *                                                                          *
  82. *   Statusaenderungen im Level 2 (Connects, Disconnects, Failures, usw.)   *
  83. *   werden hoeheren Leveln vom Level 2 aus ueber                           *
  84. *                                                                          *
  85. *     l2tolx(<status>)  ->  l2tol3(<status>), l2tol7(<status>,lnkpoi,2)    *
  86. *                                                                          *
  87. *   mitgeteilt.                                                            *
  88. *                                                                          *
  89. *   Ein Connectwunsch wird dem Level 2 ueber das Besetzen eines leeren     *
  90. *   Linkblocks mit Quell- und Ziel- sowie Digicalls und Aufrufen von       *
  91. *   newlnk() mitgeteilt (lnkpoi zeigt auf Linkblock !).                    *
  92. *   Ein newlnk() auf einen bestehenden Link erzeugt einen Link Reset.      *
  93. *                                                                          *
  94. *   Ein Disconnectwunsch (oder bei mehrmaligem Aufruf der sofortige        *
  95. *   Disconnect) wird ueber das Setzen von lnkpoi auf den jeweiligen        *
  96. *   Linkblock und Aufruf von dsclnk() erreicht.                            *
  97. *                                                                          *
  98. *   Der Informationstransfer zum Level 2 geschieht von aussen durch        *
  99. *   Aufruf von itolnk(...), vom Level 2 durch itolx(..), welches dann      *
  100. *   fmlink() aus dem hoeheren Level aufruft.                               *
  101. *                                                                          *
  102. *   Ueber sdui(..) koennen unproto-Pakete (UI-Frames) gesendet werden.     *
  103. *                                                                          *
  104. *   Level-3-Pakete (Level-3-UI-Pakete oder Infopakete in Sequenz eines     *
  105. *   Level-2-3-Links) werden ausgefiltert und in die Level-3-Frameliste     *
  106. *   eingehaengt.                                                           *
  107. *                                                                          *
  108. \**************************************************************************/
  109.  
  110. VOID l2()
  111.   {
  112.     l2tx();                             /* der Sender                     */
  113.     l2rx();                             /* der Empfaenger                 */
  114.     l2rest();                           /* sonstiges                      */
  115.   }
  116.  
  117.  
  118.  
  119.  
  120.  
  121. /**************************************************************************\
  122. *                                                                          *
  123. * "level 2 transmitter"                                                    *
  124. *                                                                          *
  125. * Falls Infopakete zu senden sind, laut Sendefenster keine Infopakete      *
  126. * ausstehen, und laut Sendestatus auch gesendet werden duerfen, diese      *
  127. * senden.                                                                  *
  128. *                                                                          *
  129. * Frames aus Gesendet-Liste holen und in die Monitorframeliste umhaengen   *
  130. * (Firmware) oder deallokieren. Entsprechend dem Frameinhalt ggf. Timer 1  *
  131. * starten.                                                                 *
  132. *                                                                          *
  133. \**************************************************************************/
  134.  
  135. VOID l2tx()
  136.   {
  137.     register unsigned    n;            /* Laufindex                       */
  138.     register unsigned    l2state;      /* aktueller Linkstate             */
  139.     register MBHEAD     *sfbp;         /* Sendeframebufferpointer         */
  140.  
  141.     for (n = LINKNMBR, lnkpoi = lnktbl; n != 0; --n, ++lnkpoi)
  142.       if (    (l2state = lnkpoi->state) == L2SIXFER           /* duerfen  */
  143.            ||                   l2state == L2SRS              /* wir was  */
  144.            ||                   l2state == L2SDBS             /* senden ? */
  145.            ||                   l2state == L2SRSDBS
  146.          )                                                    
  147.         if (lnkpoi->VS == lnkpoi->lrxdNR)         /* nichts ausstehend ?  */
  148.           sdi(lnkpoi->k);                         /* dann Infos senden    */
  149.  
  150.     while ((sfbp = stfl.head) != &stfl)           /* Gesendetliste        */
  151.       {                                           /* aufraeumen :         */
  152.         unlink(sfbp);                             /* Frame holen          */
  153.         if ((sfbp->l2fflg & L2FT1ST) != NO)       /* ist T1 zu starten ?  */
  154.           {                                       /* ja, Zeiger auf Link- */
  155.             lnkpoi = sfbp->l2link;                /* block (zum Frame)    */
  156.             setT1();                              /* und T1 starten       */
  157.           }
  158.  
  159. #ifdef FIRMWARE
  160.         if (nmbfre > 64)                          /* falls noch genug     */
  161.           relink(sfbp,monfl.tail);                /* Platz, Frame in den  */
  162.         else                                      /* Monitor              */
  163. #endif
  164.  
  165.         dealmb(sfbp);                             /* oder deallokieren    */
  166.       }
  167.   }
  168.  
  169.  
  170.  
  171.  
  172.  
  173. /**************************************************************************\
  174. *                                                                          *
  175. * "level 2 receiver"                                                       *
  176. *                                                                          *
  177. * Alle Frames aus der RX-Frameliste holen und analysieren. Kopie an        *
  178. * Monitorliste, digipeaten oder in Level-3-Liste, falls erforderlich.      *
  179. * Auf UI-Frames antworten, falls erforderlich.                             *
  180. *                                                                          *
  181. * Reaktion entsprechend Protokoll, siehe unten.                            *
  182. *                                                                          *
  183. \**************************************************************************/
  184.  
  185. VOID l2rx()
  186.   {
  187.     char       *source;                /* Zeiger auf Quellrufzeichen/SSID */
  188.     register unsigned    l2state;      /* aktueller Level 2 Linkstatus    */
  189.     register unsigned    n;            /* Laufindex                       */
  190.     register MBHEAD     *fbp;          /* Framebufferpointer lokal        */
  191.     BOOLEAN     tome;                  /* YES = Frame ist an mich         */
  192.     LNKBLK     *lblkp;                 /* Linkblockpointer lokal          */
  193.  
  194.  
  195.  
  196.     while ((fbp = rxfl.head) != &rxfl)            /* solange empfangene   */
  197.       {                                           /* Frames vorhanden     */
  198.         unlink(fbp);                              /* eins aus Liste holen */
  199.         
  200.         if (!takfhd(fbp))                         /* Kopf analysieren,    */
  201.           {                                       /* wenn nicht ok, dann  */
  202.             dealmb(fbp);                          /* wegwerfen und zum    */
  203.             continue;                             /* naechsten            */
  204.           }
  205.           
  206.         fbp->type = 2;                            /* wir sind im Level 2  */
  207.  
  208. #ifdef STATSCMD
  209.         L2HDCNT[fbp->l2port & MAXPORTMASK]++;    /* bump heard packet count*/
  210. #endif        
  211. #ifdef FIRMWARE
  212.         if (nmbfre > 64)                          /* wenn genug Platz,    */
  213.           relink(cpyfb(fbp),monfl.tail);          /* Kopie an Monitor     */
  214. #endif
  215. #ifdef KISSMODE
  216.         if( (crlmod == 3) && !ishost() && nmbfre > 64 ) /* if not host, and */
  217.             send_to_other_port( cpyfb( fbp ) ); /* mode 3 and KISS, copy it */
  218. #endif
  219. #ifdef MONITORCMD
  220.         if( mhlcount )                            /* if heard list running */
  221. #ifdef L3MONITOR
  222.             checkheard(&heardl, txfhdr, mhlcount);/* update heard list     */
  223. #else
  224.             checkheard();
  225. #endif
  226. #endif
  227.         if (digipt(fbp) /*== YES*/) continue;     /* ... nur Digipeater   */
  228.  
  229.         if (rxfctl == L2CUI)                      /* UI-Frame,            */
  230.           {                                       /* wenn an mich, und    */
  231.             if (istome(rxfhdr) /*== YES*/)        /* Antwort erwuenscht,  */
  232.             { if (rxfPF != NO && rxfCR != NO)     /* entsprechend         */
  233.                 xdm();                            /* beantworten          */
  234.             }
  235.             lnkpoi = NULL;                        /* fuer tol3sw()        */
  236. #ifdef KISSMODE
  237.             if( (crlmod == 2) && !ishost() &&     /* kiss copy, but only if*/
  238.                 nmbfre > 64 && !cmpid( myid, rxfhdr ) ) /* mode 2 now !    */
  239.                 send_to_other_port( cpyfb( fbp ) );
  240. #endif
  241.             if (!tol3sw(fbp))                     /* Level 3 UI-Frame ?   */
  242.               dealmb(fbp);                        /* nein -> weg damit    */
  243.             continue;                             /* naechstes Frame      */
  244.           }
  245.  
  246.  
  247.  
  248.         /* Haben wir einen zum Frame passenden Linkblock ?                */
  249.         /*                                                                */
  250.         /* Alle Linkbloecke durchgucken. Wenn ein aktiver Linkblock       */
  251.         /* gefunden wurde, dessen Quellcall mit dem Framezielcall         */
  252.         /* uebereinstimmt, tome auf TRUE setzen. Wenn auch noch Blockport */
  253.         /* mit Frameport und Blockzielcall mit Framequellcall             */
  254.         /* uebereinstimmen, dann ist der aktive passende Link gefunden,   */
  255.         /* Schleife abbrechen.                                            */
  256.         /*                                                                */
  257.         /* Falls ein Link inaktiv ist, aber das Framezielcall an mich     */
  258.         /* (Call + SSID oder Ident mit beliebiger SSID) ist, oder das     */
  259.         /* Blockquellcall mit dem Framezielcall uebereinstimmt, dann      */
  260.         /* Blockadresse in lblkp merken. Es wird nur der erste solche     */
  261.         /* Block genommen.                                                */
  262.  
  263.         for ( tome = NO, lblkp = NULL, n = 0, lnkpoi = lnktbl;
  264.               n < LINKNMBR;
  265.               ++n, ++lnkpoi
  266.             )
  267.           if (lnkpoi->state != L2SDSCED)
  268.             {
  269.               if (cmpid(lnkpoi->srcid,rxfhdr) /* == TRUE */ )
  270.                 {
  271.                   tome = YES;
  272.                   if (    lnkpoi->liport == rxfprt
  273.                        && cmpid(lnkpoi->dstid,rxfhdr + L2IDLEN) /* == TRUE */
  274.                      ) break;
  275.                 }
  276.             }
  277.           else
  278.             if (    !lblkp
  279.                  && (    (    *lnkpoi->srcid == '\0'
  280.                            && istome(rxfhdr) /* == TRUE */
  281.                          )
  282.                       || (    *lnkpoi->srcid != '\0'
  283.                            && cmpid(lnkpoi->srcid,rxfhdr) /* == TRUE */
  284.                          )
  285.                     )
  286.                ) lblkp = lnkpoi;
  287.  
  288.  
  289.         if (n == LINKNMBR)                   /* wenn kein aktiver Link    */
  290.           if (lblkp)                         /* passst, aber inaktiver    */
  291.             lnkpoi = lblkp;                  /* Link, dann diesen nehmen  */
  292.           else
  293.             {                                /* sonst, wenn trotzdem das  */
  294.               if (    tome == YES            /* Frame an mich gerichtet   */
  295.                    || istome(rxfhdr) /*== TRUE  ist, reagieren :          */
  296.                  )
  297.                 {
  298. #ifdef STATSCMD
  299.                   L2RXCNT[fbp->l2port & MAXPORTMASK]++;    /* recvd ++ */
  300. #endif
  301.                   if (rxfctl == L2CSABM)     /* SABM mit DM beantworten   */
  302.                     {                        /* und hoeheren Leveln       */
  303.                       l2tolx(L2MBUSYT);      /* melden                    */
  304.                       xdm();
  305.                     }
  306.                   else                       /* sonst nur antworten, wenn */
  307.                     if (    rxfPF != 0       /* Command mit Poll, dann    */
  308.                          && rxfCR != 0       /* mit DM antworten          */
  309.                        ) xdm();
  310.                     else                     /* oder wenn kein Command    */
  311.                       if (rxfctl == L2CDISC) /* Poll, aber ein DISC, mit  */
  312.                         xua();               /* UA antworten              */
  313.                 }
  314. #ifdef KISSMODE
  315.               else if( (crlmod == 2) && !ishost() && nmbfre > 64 )
  316.               {
  317.                    send_to_other_port(  fbp );
  318.                    continue;
  319.               }
  320. #endif
  321.               dealmb(fbp);                   /* empfangenes Frame weg-    */
  322.               continue;                      /* werfen und zum naechsten  */
  323.             }
  324.                 
  325.  
  326.  
  327.         /* Falls Timer 3 aktiv, diesen neu setzen, es ist wieder          */
  328.         /* Aktivitaet auf dem Link                                        */
  329.  
  330. #ifdef STATSCMD
  331.         L2RXCNT[fbp->l2port & MAXPORTMASK]++;    /* bump recvd packet count*/
  332. #endif
  333.  
  334.         if (lnkpoi->T3 != 0) setT3();
  335.  
  336.  
  337.         l2state = lnkpoi->state;        /* Linkstatus zur Abfrage         */
  338.         
  339.         if (!(rxfctl & L2CNOIM))        /* I-Frame ?                      */
  340.           {
  341.           
  342.             /* I-Frame :                                                  */
  343.             /*                                                            */
  344.             /* Nur annehmen, wenn empfangene N(R) des Frames ok,          */
  345.             /* srxdNR(), und das I-Frame das naechste erwartete in der    */
  346.             /* Sequenz ist, isntxi().                                     */
  347.             /* Wenn alles ok, Laenge pruefen und ggf. auf falsche Laenge  */
  348.             /* mit Frame-Reject reagieren, sonst Antwort entsprechend     */
  349.             /* Statetable und I-Frame verarbeiten.                        */
  350.  
  351.             if (    srxdNR() /*== TRUE*/               /* N(R) ok ?       */
  352.                  && isnxti() /*== TRUE */              /* erwartet ?      */
  353.                )
  354.  
  355.             /* if support for soft MTUs is required ( as defined by       */
  356.             /* MOD_MTU ) then use RAM version instead of fixed value      */
  357.  
  358. #ifdef MOD_MTU
  359.               if (fbp->mbpc - fbp->mbgc <= mtu_i_max)  /* Laengenpruefung */
  360. #else
  361.               if (fbp->mbpc - fbp->mbgc <= 257)  /* Laengenpruefung */
  362. #endif
  363.                 {
  364.                   l2stma(!rxfPF ? stbl01 : stbl00);    /* Statetable      */
  365.  
  366.                   /* Linkzustand I-Transfer moeglich und nicht busy ? */
  367.  
  368.                   if (l2state >= L2SIXFER && !(lnkpoi->flag & L2FBUSY))
  369.                     {
  370.  
  371.                       /* wenn Level-3-I-Paket, dann in Level-3-RX-Liste   */
  372.                       /* einhaengen und Link als Level-3-Link markieren,  */
  373.                       /* No-Activity-Timeout neu starten                  */
  374.  
  375.                       if (tol3sw(fbp) /*== YES*/)
  376.                         {
  377.                           lnkpoi->flag |= L2FL3LNK;
  378.                           lnkpoi->noatou = ininat;
  379.                         }
  380.                       else
  381.  
  382.                         /* wenn normales Level-2-I-Paket, wenn nicht Busy */
  383.                         /* oder Level-3-Link, I annehmen und in           */
  384.                         /* Linkempfangsliste einhaengen                   */
  385.  
  386.                         if (!(lnkpoi->flag & (L2FDSLE | L2FL3LNK)))
  387.                           {
  388.                             relink(fbp,lnkpoi->rcvdil.tail);
  389.                             ++lnkpoi->rcvd;
  390.                           }
  391.                         else
  392.                           dealmb(fbp);  /* ansonsten Paket wegwerfen      */
  393.                       continue;         /* auf zum naechsten Paket        */
  394.                     }
  395.                 }
  396.               else                      /* Frame zu lang :                */
  397.                 sdfrmr(0x03);           /* "U/S-Frame mit unerlaubtem     */
  398.                                         /* Infofeld"                      */
  399.           }
  400.  
  401.  
  402.  
  403.         else                                 /* kein I-Frame :            */
  404.           if (!(rxfctl & L2CNOSM))
  405.             {
  406.             
  407.               /* S-Frame :                                                */
  408.               /*                                                          */
  409.               /* Nur annehmen, wenn empfangene N(R) des Frames ok,        */
  410.               /* srxdNR(), und wenn das Frame kein Infofeld enthaelt.     */
  411.               /*                                                          */
  412.               /* Auf RR, RNR, REJ entsprechend Statetable antworten, auf  */
  413.               /* andere mit Frame-Reject antworten.                       */
  414.  
  415.               if (srxdNR() /*== YES*/)                 /* N(R) ok ?       */
  416.                 if (fbp->mbgc == fbp->mbpc)            /* kein I-Feld ?   */
  417.                   switch ((rxfctl >> 2) & 0x03)
  418.                     {
  419.                     
  420.                       case 0 :                         /* L2CRR >> 2      */
  421.                         l2stma(   !rxfCR
  422.                                 ? (!rxfPF ? stbl11 : stbl10)
  423.                                 : (!rxfPF ? stbl03 : stbl02)
  424.                                );
  425.                       break;
  426.                       
  427.                       case 1 :                         /* L2CRNR >> 2     */
  428. #ifdef STATSCMD
  429.                         L2RXRNR[fbp->l2port & MAXPORTMASK]++; /* recvd RNR */
  430. #endif
  431.                         l2stma(   !rxfCR
  432.                                 ? (!rxfPF ? stbl15 : stbl14)
  433.                                 : (!rxfPF ? stbl07 : stbl06)
  434.                                );
  435.                       break;
  436.                       
  437.                       case 2 :                         /* L2CREJ >> 2     */
  438. #ifdef STATSCMD
  439.                         L2RXREJ[fbp->l2port & MAXPORTMASK]++; /* recvd REJ */
  440. #endif
  441.                         l2stma(   !rxfCR
  442.                                 ? (!rxfPF ? stbl13 : stbl12)
  443.                                 : (!rxfPF ? stbl05 : stbl04)
  444.                                );
  445.                         if (l2state >= L2SIXFER) sdoi();
  446.                       break;
  447.                       
  448.                       default :
  449.                         sdfrmr(0x01);   /* "Kontrollfeld falsch oder      */
  450.                       break;            /* nicht implementiert"           */
  451.                       
  452.                     } /* end switch ((rxfctl >> 2) & 0x03) */
  453.                 else
  454.                   sdfrmr(0x03);         /* "U/S-Frame mit unerlaubtem     */
  455.                                         /* Infofeld"                      */
  456.             } /* end S-Frame */
  457.  
  458.  
  459.             
  460.           else                               /* kein I- oder S-Frame :    */
  461.             if ((rxfctl & 0xFF) != L2CFRMR)
  462.  
  463.               /* Kein FRMR-Frame, Frame nur annehmen, wenn kein Infofeld  */
  464.               /* vorhanden.                                               */
  465.               /*                                                          */
  466.               /* Frame auswerten, reagieren, nach Statetable antworten.   */
  467.  
  468.               if (fbp->mbgc == fbp->mbpc)
  469.                 switch (rxfctl)
  470.                   {
  471.  
  472.  
  473.  
  474.                     case L2CSABM :             /* neuer Link / Linkreset  */
  475.                       lnkpoi->V2link = rxfV2;  /* Protokollversion merken */
  476.                       switch (l2state)
  477.                         {                      /* neuer Link (Connect) ?  */
  478.                           case L2SDSCED :
  479.                             if (    fvalca(VCpar,rxfhdr + L2IDLEN) == TRUE
  480.                                  && nmblks < Ypar
  481. #ifdef ACL
  482.                                  && !(( acl_mask & ACL_BAR_L2_IC ) &&
  483.                                       (acl_entry(rxfhdr+L2IDLEN)&ACL_BAR_L2_IC))
  484. #endif
  485. #ifdef MODIFIED
  486.                                  && !( (no_digi & 1) && *(rxfhdr+L2ILEN) )
  487. #endif
  488.                                  && nmbfre > 128       /* annehmbar ?     */
  489.                                )
  490.                               {
  491.                                 inilnk();              /* ja, Link init.  */
  492.                                 ++nmblks;              /* neuer Link      */
  493.                                 l2tolx(L2MCONNT);      /* melden          */
  494. #ifdef MANAGED
  495.                                 l2audit( AudCon );     /* audit connect */
  496. #endif
  497.                                 lnkpoi->noatou = ininat;
  498. #ifdef MODIFIED
  499.                                 /* if help message enabled for i/c connects
  500.                                  * and the connect is to the alias, force a
  501.                                  * connection to the level 7 switch
  502.                                  * Also, if extra aliases are enabled, check
  503.                                  * for them & kick upstairs if located
  504.                                  */
  505.                                 if((( hlpflg & 8 ) && cmpcal( alias, rxfhdr ))
  506.                                    ||
  507.                                    ( enaliases && ( cmpcal( bbsalias, rxfhdr )
  508.                                       || cmpcal( hostalias, rxfhdr )
  509.                                       || cmpcal( dxcalias, rxfhdr ))))
  510.                                 {
  511.                                      relink(fbp,lnkpoi->rcvdil.tail);
  512.                                      ++lnkpoi->rcvd;
  513.                                      l2stma(stbl08);
  514.                                      continue;
  515.                                 }
  516.                                 else
  517. #endif
  518.                                 break;                 /* -> Statetable   */
  519.                               }
  520.                             l2tolx(L2MBUSYT);          /* nein, melden    */
  521.                             xdm();                     /* mit DM antwort. */
  522.                             dealmb(fbp);               /* Frame vergessen */
  523.                             continue;                  /* naechstes Paket */
  524.                           break;
  525.                           
  526.                           case L2SLKSUP :              /* beide connecten */
  527.  
  528.                             /* anderer Weg als selbst benutzt ? */
  529.  
  530.                             if ( !cmpidl(   cmpid(rxfhdr + L2IDLEN,
  531.                                                   lnkpoi->srcid) /*== TRUE*/
  532.                                           ? rxfhdr + L2ILEN
  533.                                           : txfhdr + L2ILEN,
  534.                                           lnkpoi->viaidl
  535.                                         )
  536.                                )
  537.                               {
  538.                                 clrlnk();                   /* ja, alles  */
  539.                                 l2tolx(L2MBUSYF);           /* abbrechen  */
  540.                                 xdm();
  541.                                 lnkpoi->state = L2SDSCED;
  542.                                 dealmb(fbp);
  543.                                 continue;
  544.                               }
  545.                             else
  546.                               {
  547.                                 reslnk();                   /* nein,      */
  548.                                 l2tolx(L2MCONNT);           /* gelungener */
  549.                                 lnkpoi->noatou = ininat;    /* Connect    */
  550.                               }
  551.                           break;
  552.                           
  553.                           case L2SDSCRQ :         /* sind ge-disct, Link  */
  554.                             mclrlk();             /* aufloesen und melden */
  555.                           break;
  556.                           
  557.                           default :               /* normaler Linkreset   */
  558.                             inilnk();             /* vom Partner          */
  559.                             l2tolx(L2MLRESF);
  560.                           break;
  561.                              
  562.                         } /* end switch (l2state) */
  563.                       l2stma(stbl08);             /* SABM EITHER COMMAND  */
  564.                     break;
  565.  
  566.  
  567.  
  568.                     case L2CDISC :
  569.                       if (!l2state)               /* Link aktiv ?         */
  570.                         {
  571.                           if (    rxfPF != 0      /* nein, wenn Command   */
  572.                                && rxfCR != 0      /* mit Poll, dann mit   */
  573.                              ) xdm();             /* DM antworten         */
  574.                           else
  575.                             xua();                /* sonst mit UA         */
  576.                           dealmb(fbp);            /* Frame wegwerfen      */
  577.                           continue;               /* naechstes Paket      */
  578.                         }
  579.                       else                        /* ja,                  */
  580.                       {
  581. #ifdef MANAGED
  582.                         l2audit( AudDisc );       /* audit disconnect msg */
  583. #endif
  584.                         if (l2state == L2SLKSUP)  /* wenn im Linkaufbau,  */
  585.                           {                       /* dann Link sofort     */
  586.                             clrlnk();             /* aufloesen und melden */
  587.                             l2tolx(L2MBUSYF);
  588.                           }
  589.                         else                      /* sonst erst restliche */
  590.                           {                       /* I-Frames an hoeheren */
  591.                             i2tolx(YES);          /* Level geben und dann */
  592.                             mclrlk();             /* Link loesen / melden */
  593.                           }
  594.                       }
  595.                       l2stma(stbl09);             /* DISC EITHER COMMAND  */
  596.                     break;
  597.  
  598.  
  599.  
  600.                     case L2CUA :
  601.                       if (l2state < L2SRS)             /* V1-Zustand ?    */
  602.                         {
  603.                           if (l2state == L2SLKSUP)     /* ja, wenn im     */
  604.                             {                          /* Link-Setup      */
  605.                               lnkpoi->V2link = rxfV2;  /* Protokollvers.  */
  606.                               reslnk();                /* uebernehmen,    */
  607.                               l2tolx(L2MCONNT);        /* Link neu und    */
  608. #ifdef MANAGED
  609.                               l2audit( AudConAcc );    /* audit connect accept*/
  610. #endif
  611.                               lnkpoi->noatou = ininat; /* melden          */
  612.                             }
  613.                           else                         /* sonst wenn im   */
  614.                             if (l2state == L2SDSCRQ)   /* Disc-Request    */
  615.                             {
  616. #ifdef MANAGED
  617.                                l2audit( AudDiscAcc );  /* audit disc accept */
  618. #endif
  619.                                mclrlk();               /* Link aufloesen  */
  620.                             }
  621.                         }
  622.                       else
  623.                         {
  624.                           reslnk();                    /* nein, Linkreset */
  625.                           l2tolx(L2MLREST);            /* ausf. / melden  */
  626.                         }
  627.                       l2stma(stbl16);             /* UA EITHER RESPONSE   */
  628.                     break;
  629.  
  630.  
  631.  
  632.                     case L2CDM :
  633.                       if (l2state)                /* wenn Link aktiv ...  */
  634.                         if (l2state == L2SLKSUP)  /* wenn DM beim Link-   */
  635.                           {                       /* Setup, dann Link     */
  636.                             clrlnk();             /* sofort aufloesen und */
  637.                             l2tolx(L2MBUSYF);     /* "Busy from" melden   */
  638.                           }
  639.                         else                      /* sonst Link aufloesen */
  640.                           mclrlk();               /* mit Meldung          */
  641.                       l2stma(stbl17);             /* DM EITHER RESPONSE   */
  642.                     break;
  643.                     
  644.  
  645.  
  646.                     default :           /* unbekanntes Kontrollfeld :     */
  647.                       sdfrmr(0x01);     /* "Kontrollfeld falsch oder      */
  648.                     break;              /* nicht implementiert"           */
  649.  
  650.  
  651.  
  652.                   } /* end switch (rxfctl) */
  653.               else                                /* Frametyp unbekannt   */
  654.                 sdfrmr(0x03);                     /* "U/S-Frame mit un-   */
  655.                                                   /* erlaubtem Infofeld"  */
  656.  
  657.  
  658.  
  659.             else /* from if (rxfctl != L2CFRMR) */
  660.               {
  661.               
  662.                 /* FRMR-Frame :                                           */
  663.                 /*                                                        */
  664.                 /* Wird nur im Frame-Reject-Zustand oder bei moeglichem   */
  665.                 /* Informationstransfer angenommen.                       */
  666.                 /* Es werden die FRMR-Infobytes gelesen, FRMR an die      */
  667.                 /* hoeheren Level gemeldet, nach Statetable geantwortet.  */
  668.  
  669.                 if (l2state >= L2SIXFER || l2state == L2SFRREJ)
  670.                   {
  671.                     /* FRMR-Infobytes im Linkblock merken */
  672.                     for (source = lnkpoi->frmr, n = 3; n != 0; --n)
  673.                       *source++ = (fbp->mbgc < fbp->mbpc) ? getchr(fbp) : 0;
  674.                     l2tolx(L2MFRMRF);
  675.                   }
  676.                 l2stma(stbl18);                   /* FRMR EITHER RESPONSE */
  677.  
  678.               }
  679.         
  680.  
  681.       
  682.         dealmb(fbp);          /* aktuelles Frame verarbeitet, wegwerfen   */
  683.              
  684.       } /* end while ((fbp = rxfl.head) != &rxfl) */
  685.   }
  686.  
  687.  
  688.  
  689.  
  690.  
  691. /**************************************************************************\
  692. *                                                                          *
  693. * "level 2 rest"                                                           *
  694. *                                                                          *
  695. * Fuer alle aktiven Links Busyzustand pruefen/setzen/aufloesen, I-Pakete   *
  696. * unter Beruecksichtigung der "Erstickungskontrolle" an hoehere Level      *
  697. * weiterreichen. Fall Zustand "Disconnecten nach Uebertragung der          *
  698. * restlichen I-Pakete" und keine I-Pakete mehr zu senden, Disconnect       *
  699. * einleiten.                                                               *
  700. * Muellbufferliste frei machen (aus Interruptroutinen entstandener Muell,  *
  701. * der besser ausserhalb der Interrupts deallokiert wird aus Zeitgruenden). *
  702. *                                                                          *
  703. \**************************************************************************/
  704.  
  705. VOID l2rest()
  706.   {
  707.     register unsigned n;
  708.  
  709.  
  710.     for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
  711.       if (lnkpoi->state != L2SDSCED)
  712.         {
  713.         
  714.           /* fuer alle aktiven (= nicht disconnecteten) Links : */
  715.  
  716.  
  717.           txfV2 = lnkpoi->V2link;                  /* Protokollversion    */
  718.  
  719.           /* wenn Zustand "nachdem alle restliche I's uebertragen wurden, */
  720.           /* disconnecten" und alle I's uebertragen, DISC einleiten       */
  721.  
  722.           if (    ((lnkpoi->flag & L2FDSLE) != NO)
  723.                && !lnkpoi->tosend
  724.              ) disc();
  725.  
  726.           /* sonst empfangene I-Pakete an hoeheren Level uebertragen und  */
  727.           /* Busy-Condition pruefen / setzen / aufheben                   */
  728.           /*                                                              */
  729.           /* "Busy werden"      -   weniger als 80 Freibuffer             */
  730.           /*                        oder so viele I-Pakete empfangen und  */
  731.           /*                        nicht abgeholt, wie                   */
  732.           /*                        "Erstickungszaehler" conctl angibt    */
  733.           /*                                                              */
  734.           /* "Busy aufloesen"   -   wieder mehr als 112 Freibuffer        */
  735.           /*                        und weniger als halb so viele         */
  736.           /*                        empfangen und nicht abgeholt wie      */
  737.           /*                        conctl angibt                         */
  738.  
  739.           else
  740.             {
  741.               i2tolx(NO);
  742.               if (!(lnkpoi->flag & L2FBUSY))     /* nicht busy            */
  743.                 {
  744.                   if (nmbfre < 80 || lnkpoi->rcvd >= conctl)
  745.                     {
  746.                       lnkpoi->flag |= L2FBUSY;   /* busy werden           */
  747.                       l2stma(stbl21);            /* STATION BECOMES BUSY  */
  748.                     }
  749.                 }
  750.               else
  751.                 if (nmbfre > 112 && lnkpoi->rcvd < conctl/2)
  752.                   {
  753.                     lnkpoi->flag &= ~L2FBUSY;    /* "busy" aufloesen      */
  754.                     l2stma(stbl22);              /* BUSY CONDITION CLEARS */
  755.                   }
  756.             }     
  757.         } /* end if (lnkpoi->state) */
  758.  
  759.     dealml(&trfl);                      /* Muellbufferliste frei machen   */
  760.   }
  761.  
  762.  
  763.  
  764.  
  765.  
  766. /**************************************************************************\
  767. *                                                                          *
  768. * "level 2 timer"                                                          *
  769. *                                                                          *
  770. * Ausfuehren der Level-2-Millisekundentimer 1, 2, 3 in allen aktiven       *
  771. * Links (herunterzaehlen und bei Ablauf reagieren).                        *
  772. * In ticks wird die Anzahl der vergangenen 10ms-Intervalle (Ticks) seit    *
  773. * dem letzten Aufruf dieser Routine angegeben.                             *
  774. *                                                                          *
  775. \**************************************************************************/
  776.  
  777. VOID l2timr(ticks)
  778. register unsigned ticks;
  779. {
  780.     register unsigned n;
  781.  
  782.     for (n = LINKNMBR, lnkpoi = lnktbl; n != 0; --n, ++lnkpoi)
  783.       if (lnkpoi->state != L2SDSCED)
  784.         {
  785.         
  786.           /* fuer alle aktiven (= nicht disconnecteten) Links : */
  787.  
  788.  
  789.           txfV2 = lnkpoi->V2link;       /* Merker ob Version-2-Protokoll  */
  790.  
  791.           if (lnkpoi->T1 != 0)          /* wenn Timer 1 aktiv ...         */
  792.             if (lnkpoi->T1 <= ticks)    /*   wenn Timer 1 abgelaufen ...  */
  793.               {
  794.                 lnkpoi->T1 = 0;         /*   ... Timer 1 stoppen          */
  795.                 setT3();                /*   Timer 3 neu starten          */
  796.                 ++lnkpoi->tries;        /*   Retryzaehler                 */
  797.                 if (    !lnkpoi->N2
  798.                      || lnkpoi->tries < lnkpoi->N2 /* zu viele Retries ?  */
  799.                    )
  800.                   if (    lnkpoi->V2link == YES    /* nein, bei V2 oder   */
  801.                        || lnkpoi->state < L2SIXFER /* V1-Status < IXFER   */
  802.                      ) l2stma(stbl23);             /* Statet. T1 EXPIRES  */
  803.                   else                             /* sonst ausstehende   */
  804.                     sdoi();                        /* I's senden          */
  805.                 else
  806.                   {                                /* zu viele Retries :  */
  807. #ifdef STATSCMD
  808.                     L2FAILS[lnkpoi->liport & MAXPORTMASK]++; /* link failed */
  809. #endif
  810.                     lnkpoi->tries = 0;             /* Retryzaehler leer   */
  811.                     clrlnk();                      /* Link sofort loesch. */
  812.                     l2tolx(L2MFAILW);              /* "Link failure"      */
  813.                     lnkpoi->state = L2SDSCED;      /* DISCONNECTED        */
  814.                   }
  815.               }
  816.             else
  817.               lnkpoi->T1 -= ticks;      /*   sonst herunterzaehlen        */
  818.               
  819.           if (lnkpoi->T2 != 0)          /* wenn Timer 2 aktiv ...         */
  820.             if (lnkpoi->T2 <= ticks)    /*   wenn Timer 2 abgelaufen ...  */
  821.               lnkpoi->T2 = 0;           /*   ... Timer 2 stoppen          */
  822.             else
  823.               lnkpoi->T2 -= ticks;      /*   sonst herunterzaehlen        */
  824.  
  825.           if (    !lnkpoi->T2           /* wenn Timer 2 abgelaufen ist    */
  826.                && lnkpoi->RStype != 0   /* und Response zu senden ist     */
  827.                && !iscd(lnkpoi->liport) /* und der Kanal frei ist ...     */
  828.              )
  829.             {
  830.               stxfad();                 /* ... dann Responseframe bauen   */ 
  831.               txfCR = txfPF = 0;
  832.               txfctl = setNR(   !(lnkpoi->flag & L2FBUSY)
  833.                               ? lnkpoi->RStype
  834.                               : L2CRNR
  835.                            );
  836.               sdl2fr(makfhd(L2FUS));    /* und senden                     */
  837.               lnkpoi->RStype = 0;       /* Responsemodus loeschen         */
  838.             }
  839.  
  840.           if (lnkpoi->T3 != 0)          /* wenn Timer 3 aktiv ...         */
  841.             if (lnkpoi->T3 <= ticks)    /*   wenn Timer 3 abgelaufen ...  */
  842.               {
  843.                 clrT3();                /*   ... Timer 3 stoppen und      */
  844.                 l2stma(stbl24);         /*       Statetable T3 EXPIRES    */  
  845.               }                         /*       ausfuehren               */
  846.             else
  847.               lnkpoi->T3 -= ticks;      /*   sonst herunterzaehlen        */
  848.  
  849.         }
  850. }
  851.  
  852. /**************************************************************************\
  853. *                                                                          *
  854. * "kiss mode driver support"                                               *
  855. *                                                                          *
  856. * This function sends a packet to the other port ( came in on HDLC,        *
  857. * ie port 0 , goes out on port 1, RS232 ) and vica versa                   *
  858. *                                                                          *
  859. \**************************************************************************/
  860.  
  861. #ifdef KISSMODE
  862. send_to_other_port(fbp)
  863. register MBHEAD *fbp;
  864. {
  865.     fbp->l2port ^= 1;        /* change port 0 -> 1 and 1 -> 0 */
  866.     fbp->l2fflg = 0;
  867.     sdl2fr( fbp );            /* send the packet */
  868. }
  869. #endif
  870.  
  871. /**************************************************************************\
  872. *                                                                          *
  873. * "level 2 audit handler"                                                  *
  874. *                                                                          *
  875. * This function audits a connection or disconnection for a level 2         *
  876. * connection by sending a notify message to all ccp users at level 6       *
  877. *                                                                          *
  878. \**************************************************************************/
  879.  
  880. #ifdef MANAGED
  881. l2audit( what )
  882. char *what;
  883. {
  884.     if( auditmask & 2 )
  885.         notify( L2audit, 6, lnkpoi->srcid, lnkpoi->dstid, what, 2 );
  886. }
  887. #endif
  888.  
  889. /* Ende von L2A.C */
  890.